package com.yiba.vpn.util;

import com.yiba.vpn.domain.User;
import org.apache.log4j.Logger;
import org.springframework.util.Base64Utils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
import java.util.UUID;

public class TokenUtil {

    private static Logger logger = Logger.getLogger(TokenUtil.class);

    private final static String DES = "DES";
    public  final static String SPLIT = "__";

    private final static String CHARACTER_ENCODING = "UTF-8";

    public static void main(String[] args) throws Exception {

        String key = "c7a8cd289f464073b766ca4f14b27c8a";
        //System.err.println(encrypt("yk-024a5e4ac55147249589f41ab58bc401_s11122122222_150995222206", key));
        System.err.println(decrypt("2b677936594258536575364b42364e6e65356273674878614e3255644f6b44796d61517057486636736579504b534c7674432f2b4461467632413270626734796245474d425536497533564b4146522b552b77386a4f6873424d6e726232397961476575636b7134644a764d6d335a52344e4c4f57513d3d", key));

    }




    public static String getToken(User user, String tokenKey) {
        String encryptToken = null;
        String token = user.getAccount() +SPLIT + user.getUuid() +SPLIT + DateUtil.getTimestamp(new Date());
        try {
            encryptToken = encrypt(token, tokenKey);
        } catch (Exception e) {
            logger.error("token加密系统失败:{}" + e);
        }
        return encryptToken;
    }


    /**
     * 获取加密的token
     *
     * @param account
     * @param tokenKey
     * @return
     * @throws Exception
     */
    public static String getEncryptRefreshToken(String account, String tokenKey) {
        String encrytreFreshToken = null;
        String reFreshToken = account +"|"+ UUID.randomUUID().toString().replace("-", "")+ "|" + DateUtil.getTimestamp(new Date());
        try {
            encrytreFreshToken = encrypt(reFreshToken, tokenKey);
        } catch (Exception e) {
            logger.error("token加密系统失败:{}" + e);
        }
        return encrytreFreshToken;
    }


    /**
     * 获取解密的token
     *
     * @param tokenKey
     * @return
     * @throws Exception
     */
    public static String getDecryptRefreshToken(String decryToken, String tokenKey) {
        String decryptFreshToken = null;
        try {
            decryptFreshToken = decrypt(decryToken, tokenKey);
        } catch (Exception e) {
            logger.error("刷新的Token解密系统失败:{}" + e);
        }
        return decryptFreshToken;
    }

    ;

    /**
     * Description 根据键值进行加密
     *
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    public static String encrypt(String data, String key) throws Exception {

        byte[] bt = encrypt(data.getBytes(CHARACTER_ENCODING), key.getBytes());
        byte[] encode = Base64Utils.encode(bt);
        return bytesToHexString(encode);
    }

    /**
     * @param @param  srcs
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: bytesToHexString
     * @Description: byte[]转 十六进制
     */
    private static String bytesToHexString(byte[] srcs) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (srcs == null || srcs.length <= 0) {
            return null;
        }
        for (byte src : srcs) {
            int v = src & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }


    /**
     * @param @param  hexString
     * @param @return 设定文件
     * @return byte[]    返回类型
     * @throws
     * @Title: hexStringToBytes
     * @Description: 十六进制转byte[]
     */
    private static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }


    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }



    /**
     * Description 根据键值进行解密
     *
     * @param data
     * @param key  加密键byte数组
     */
    public static String decrypt(String data, String key) throws IOException,
            Exception {
        if (data == null) {
            return null;
        }
        data = new String(hexStringToBytes(data));
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] buf = decoder.decodeBuffer(data);
        byte[] bt = decrypt(buf, key.getBytes(CHARACTER_ENCODING));
        return new String(bt);
    }

    /**
     * Description 根据键值进行加密
     *
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, byte[] key) throws Exception {

        Key securekey = setKey(key);
        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance(DES);
        // 用密钥初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, securekey);
        return cipher.doFinal(data);
    }


    /**
     * Description 根据键值进行解密
     *
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, byte[] key) throws Exception {

        Key securekey = setKey(key);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(DES);
        // 用密钥初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, securekey);

        return cipher.doFinal(data);
    }


    public static Key setKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        DESKeySpec keySpec = new DESKeySpec(key);
        return keyFactory.generateSecret(keySpec);
    }

}
